package core.net.socket
{
    import com.hurlant.crypto.symmetric.DESKey;
    import com.hurlant.util.Hex;
    
    import core.utils.encrypt.CRC32;
    
    import flash.events.*;
    import flash.net.*;
    import flash.system.Security;
    import flash.utils.*;
	/**
	 *  网络通讯Socket，用二进制的方式进行前后台的链接CRC加密方式
	 * @author Gaara
	 * @example
	 * <listing>
	 * //链接
	 * var socket:NetSocket = new NetSocket("192.168.1.128",8080);
	 * 
	 * //向服务器发送数据
	 * var ba:ByteArray = new ByteArray();
	 * socket.send(ba);
	 * 
	 * //向后台发送心跳数据保持通讯
	 * socket.heartBeat();
	 * </listing>
	 */	
    public class NetSocket extends EventDispatcher
    {
		private var _socket:Socket = null;
		//接收通信包头buffer,1个__socket连接1个
		private var headerBuffer:ByteArray;
		//接收有效载荷buffer,1个__socket连接1个
		private var bodyBuffer:ByteArray;
		//__socket_read_len：可读的数据长度
		private var readableLength:int;	
		//接收buffer的当前接收位置，也是已收数据长度
		private var readOffset:int;		
		private var totalLength:uint;
		private var this_packet_option_byte1:uint;
		private var this_packet_option_byte2:uint;
		private var this_packet_crc32:uint;

		public function NetSocket(server:String,port:int)
		{
			headerBuffer=new ByteArray;
				//MsgUtil.creatByteArray();
			bodyBuffer=new ByteArray;
			//MsgUtil.creatByteArray();
			_socket=new Socket();
			_socket.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
			_socket.addEventListener(Event.CLOSE, connectErrorHandler);
			_socket.addEventListener(Event.CONNECT,connectedHandler);
			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
			_socket.addEventListener(ProgressEvent.SOCKET_DATA,dataHandler);
			_socket.connect(server,port);
		}

		private function ioErrorHandler(evt:IOErrorEvent):void
		{
			trace("Connection-ioErrorHandler");
//			dispatchEvent(new NetEvent(NetEvent.ON_IOERROR));
		}		
		private function securityErrorHandler(evt:SecurityErrorEvent):void
		{
			trace("Connection-securityErrorHandler");
//			dispatchEvent(new NetEvent(NetEvent.ON_SECURITYERROR));
		}
		private function connectErrorHandler(evt:Event):void
		{
			trace("Connection-Net_Error");
//			dispatchEvent(new NetEvent(NetEvent.ON_DISCONNECT));
		}
		private function connectedHandler(evt:Event):void
		{
			trace('Connected');
//			dispatchEvent(new NetEvent(NetEvent.ON_CONNECT));
		}
		
		public function get socket(): Socket
		{
			return _socket;
		}
		public function set socket(value: Socket): void
		{
			_socket = value;
		}
		
		/**
		 *	   检测是否连接
		 **/	
		public function IsConnect():Boolean
		{
			return (_socket && _socket.connected);	
		}
		
		/** 接收数据处理器  */
		private function dataHandler(evt:ProgressEvent):void
		{
			try{
				//Socket的数据总长度
				readableLength=_socket.bytesAvailable;
				
				while(true)
				{
					//长度异常
					if(readableLength < 1)
					{
						break;
					}
					//当前已读长度
					var this_read_len:int = 0;
					//readOffset已读取的位置偏移量
					if(readOffset < 16) //16: CommHead的长度
					{
						this_read_len = 16 - readOffset;
					}
					else
					{
						this_read_len = totalLength - readOffset;
					}
					
					if(this_read_len > readableLength)
					{
						this_read_len = readableLength;
					}
					
					if(readOffset < 16)
					{
						//头信息
						_socket.readBytes(headerBuffer, readOffset, this_read_len);
					}
					else
					{
						//信息体
						_socket.readBytes(bodyBuffer, (readOffset - 16), this_read_len);
					}
					
					//	txt.text+=ByteCode.traceByte(read_buffer,'接收数据：')+'\n';
					//叠加已读取的信息长到已读位置偏移
					readOffset += this_read_len;
					//可读长度在总长度上迭减
					readableLength -= this_read_len;
					
					if(readOffset == 16)
					{
						//收全头了
						totalLength =  headerBuffer.readUnsignedShort();//read_buffer_head.readUnsignedInt();
						this_packet_option_byte1 = headerBuffer.readUnsignedByte();
						this_packet_option_byte2 = headerBuffer.readUnsignedByte();
						this_packet_crc32 = headerBuffer.readUnsignedInt();
					}
					
					if(readOffset == totalLength)
					{
						//收全整个包了
						//	var by:ByteArray=MsgUtil.creatByteArray();
						//	by.writeBytes(read_buffer,16,read_buffer.length-16);
						
						var crc:CRC32=new CRC32;
						//	crc.update(by);
						crc.update(bodyBuffer);
						var crcValue:uint=crc.getValue();
						if(crcValue== this_packet_crc32)	//crc32校验
						{
							//收到一个数据包，向上层送数据上去
							if(this_packet_option_byte1 & 0x01)//不懂
							{
							//this packet is zipped.字节组解压
								bodyBuffer.uncompress();
							}
							
		//					var msg_len:int = read_buffer_body.bytesAvailable;
		//					var msg_offset:int = 0;
							
							while(bodyBuffer.bytesAvailable>2)
							{
								//信息体包长
								var packet_len:uint = bodyBuffer.readUnsignedShort();
								//信息体的id
								var id:uint=bodyBuffer.readUnsignedShort();
								var byte:ByteArray=new ByteArray;
									//MsgUtil.creatByteArray();
								
	//							msg_offset += 4;
								bodyBuffer.position -= 2;
								bodyBuffer.readBytes(byte,0,packet_len);
								byte.position=0;
//								this.dispatchEvent(new NetEvent(NetEvent.ON_PACKET,id,byte));
								
	//							msg_offset += packet_len;
							}
						}
						else
						{
							//收到一个错误包，报错
						}
						
						totalLength = 0;
						this_packet_option_byte1 = 0;
						this_packet_option_byte2 = 0;
						this_packet_crc32 = 0;
						readOffset=0;
						headerBuffer.clear();
						bodyBuffer.clear();
					}
				}
				
			}catch(e:Error){
				trace("Connection:Net_Data()取数据异常:["+e.errorID+":"+e.name+":"+e.message+":"+e.getStackTrace()+"]");
			}
		}
		
		/*
		 * 产生通信头
		 * */
		private static var encode_p2:int = 0;
		private var key:String = 'E1A8C7A63CDC721C';
		
		/**
		 * 为消息体添加包头 
		 * @param body	消息体 ByteArray
		 * 
		 */		
		public function addHeader(body:ByteArray):void
		{
			var encryptInfo:ByteArray=new ByteArray;
				//MsgUtil.creatByteArray();//加密信息
			var encode_p1:int = int((new Date).time/1000);
			encryptInfo.writeInt(encode_p1);
			encode_p2++;
			encryptInfo.writeInt(encode_p2);
			
			var myKey:ByteArray = Hex.toArray(key);
			var des:DESKey = new DESKey(myKey);
			des.encrypt(encryptInfo);
			
			var head:ByteArray=new ByteArray;
			//MsgUtil.creatByteArray();//消息头
			head.writeShort(body.length + 16);
			head.writeShort(0x0000);
			
			var crc:CRC32=new CRC32;
			crc.update(body);
			head.writeUnsignedInt(crc.getValue());
			head.writeBytes(encryptInfo, 0, 8);
			_socket.writeBytes(head, 0, 16);
			

		}
		
		/**
		 * 向后端发送消息 
		 * @param body 发送的数据 ByteArray
		 * 
		 */			
		public function send(body:ByteArray):void
		{
//			var encrypt_info:ByteArray=MsgUtil.creatByteArray();//加密信息
//			encrypt_info.writeInt(0);
//			encrypt_info.writeInt(0);
//			
//			var head:ByteArray=MsgUtil.creatByteArray();//消息头
//			head.writeShort(body.length + 16);
//			head.writeShort(0x0000);
//			
////			var body_len:ByteArray=MsgUtil.creatByteArray();
////			body_len.writeShort(body.length);
//	
//			var crc:CRC32=new CRC32;
////			crc.update(body_len);
//			crc.update(body);
//			head.writeUnsignedInt(crc.getValue());
//			head.writeBytes(encrypt_info, 0, 8);
//			socket.writeBytes(head, 0, 16);
			//write frame info
//			socket.writeShort(body.length);
			//write message
			addHeader(body);
			_socket.writeBytes(body, 0, body.length);
			_socket.flush();
		}
		
		/**
		 * 发送心跳包到服务端：纯包头 
		 * 
		 */		
		public function heartBeat():void
		{
			addHeader(new ByteArray);
			_socket.flush();
		}
    }
}
